﻿using BCCommon;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TMSWorkflowSpecificFormAutoJob
{
    public class MySqlContext : IDatabaseContext
    {
        private readonly MySqlOptions options;

        private int transactionCount = 0;

        private int masterAccessCount = 0;
        private int slaveAccessCount = 0;
        private int transactionBeginCount = 0;

        public IDbConnection Master
        {
            get
            {
                this.masterAccessCount++;
                return this.Transaction != null ? this.Transaction.Connection : new MySqlConnection(options.MasterConnectionString);
            }
        }

        public IDbConnection Slave
        {
            get
            {
                this.slaveAccessCount++;
                return this.Transaction != null ? this.Transaction.Connection : new MySqlConnection(options.SlaveConnectionString);
            }
        }

        public IDbTransaction Transaction { get; private set; }

        public MySqlContext(MySqlOptions options)
        {
            this.options = options;
        }

        public void BeginTransaction()
        {
            lock (this)
            {
                this.transactionCount++;
                this.transactionBeginCount++;

                if (this.Transaction == null)
                {
                    var connection = new MySqlConnection(options.MasterConnectionString);

                    connection.Open();

                    this.Transaction = connection.BeginTransaction();
                }
            }
        }

        public void BeginTransaction(IsolationLevel isolationLevel)
        {
            lock (this)
            {
                this.transactionCount++;

                if (this.Transaction == null)
                {
                    var connection = new MySqlConnection(options.MasterConnectionString);

                    connection.Open();

                    this.Transaction = connection.BeginTransaction(isolationLevel);
                }
            }
        }

        public void Commit()
        {
            lock (this)
            {
                this.transactionCount--;

                if (this.transactionCount == 0)
                {
                    this.Transaction.Commit();
                    this.Transaction.Connection.Close();

                    this.Transaction = null;
                }
            }
        }

        public void Rollback()
        {
            lock (this)
            {
                this.EnsureCloseTransaction();
            }
        }

        public void Dispose()
        {
#if DEBUG
            Console.WriteLine($"数据库访问统计: 请求主库 {this.masterAccessCount} 次，请求从库 {this.slaveAccessCount} 次，启动事务 {this.transactionBeginCount} 次。注意: 该统计不代表实际数据库查询次数。");
#endif
            this.EnsureCloseTransaction();
        }

        private void EnsureCloseTransaction()
        {
            if (this.Transaction != null)
            {
                this.transactionCount = 0;

                this.Transaction.Rollback();
                this.Transaction.Connection.Close();

                this.Transaction = null;
            }
        }
    }
}
